package model

import (
	"fmt"
	"github.com/hwcer/cosgo/values"
	"github.com/hwcer/yyds"
	"server/share/config"
	"strconv"
	"strings"
	"time"
)

type MailStatus int8

const (
	MailStatusNone   MailStatus = 0 //新邮件
	MailStatusRead              = 1 //已读，可能有附件未领
	MailStatusDelete            = 9 //已删除
)
const MailExpire = 86400 * 30

func init() {
	Register(&Mail{})
}

func NewMail(uid string, iid int32, args map[string]any) *Mail {
	m := &Mail{Args: args}
	m.IID = iid
	m.Uid = uid
	m.Create = time.Now().Unix()
	m.Update = m.Create
	if iid > 0 {
		if c := config.Data.Mail[iid]; c != nil {
			if c.Expire > 0 {
				m.Expire = m.Update + int64(c.Expire)
			}
			m.AddAttrArray(c.Attr)
		}
	}
	if m.Expire == 0 {
		m.Expire = m.Create + MailExpire
	}
	return m
}

type Mail struct {
	Model  `bson:"inline"`
	Attr   []MailAttr     `json:"attr" bson:"attr"`                                                       //附件
	Args   map[string]any `json:"args" bson:"args"`                                                       //系统邮件参数
	Text   *MailText      `json:"text" bson:"text"`                                                       //多语言文本
	Status MailStatus     `json:"status" bson:"status"`                                                   //邮件状态
	Submit int8           `bson:"submit" json:"submit"`                                                   //附件数量,0-已领
	Expire int64          `bson:"expire" json:"expire"`                                                   //过期时间
	Update int64          `bson:"update" json:"-"  index:"name:_idx_uid_primary,Sort:desc,Priority:100" ` //最后更新时间
	Create int64          `bson:"create" json:"create"`                                                   //发送时间
}

func (this *Mail) Save(xid any) error {
	if this.Create == 0 {
		this.Create = time.Now().Unix()
	}
	if this.Update == 0 {
		this.Update = this.Create
	}
	if this.Expire == 0 {
		this.Expire = this.Create + MailExpire
	}
	this.Submit = int8(len(this.Attr))
	if this.OID == "" {
		this.ObjectId(xid)
	}
	return db.Create(this).Error
}

func (this *Mail) Format(txt string) string {
	for k, v := range this.Args {
		txt = strings.Replace(txt, fmt.Sprintf("{%s}", k), fmt.Sprintf("%s", v), -1)
	}
	return txt
}

func (this *Mail) Display() map[string]any {
	r := make(map[string]any)
	r["id"] = this.OID
	r["iid"] = this.IID
	r["uid"] = this.Uid
	r["attr"] = this.GetAttrString()
	r["status"] = this.Status
	r["submit"] = this.Submit
	r["expire"] = this.Expire
	r["update"] = this.Update
	if this.IID > 0 {
		if c := config.Data.Mail[this.IID]; c != nil {
			r["from"] = c.From
			r["title"] = this.Format(c.Title)
			r["content"] = this.Format(c.Content)
		}
	} else if this.Text != nil {
		r["from"] = this.Text.From
		r["title"] = this.Text.Title
		r["content"] = this.Text.Content
	}

	return r
}

type MailAttr struct {
	K int32 `json:"k" bson:"k"`
	V int32 `json:"v" bson:"v"`
}

type MailText struct {
	From    string `json:"from" bson:"from"`       //发送者
	Title   string `json:"title" json:"title"`     //标题
	Content string `json:"content" json:"content"` //内容
}

func (this *MailAttr) GetId() int32 {
	return this.K
}

func (this *MailAttr) GetNum() int32 {
	return this.V
}

func (this *Mail) Clone(uid string, xid any) *Mail {
	t := *this
	m := &t
	if len(this.Attr) > 0 {
		m.Attr = make([]MailAttr, 0, len(this.Attr))
		m.Attr = append(m.Attr, this.Attr...)
	} else {
		m.Attr = []MailAttr{}
	}

	m.Args = make(map[string]any)
	for k, v := range this.Args {
		m.Args[k] = v
	}
	m.Uid = uid
	m.ObjectId(xid)
	return m
}

func (this *Mail) AddArgs(k string, v interface{}) {
	if this.Args == nil {
		this.Args = make(map[string]interface{})
	}
	this.Args[k] = v
}

func (this *Mail) AddAttr(k, v int32) {
	if k == 0 || v == 0 {
		return
	}
	if it := yyds.Config.ITypes.GetIType(k); it == 0 {
		return
	}
	this.Attr = append(this.Attr, MailAttr{K: k, V: v})
	this.Submit += 1
}

func (this *Mail) AddAttrArray(attr []int32) {
	for i := 0; i < len(attr); i += 2 {
		if j := i + 1; j < len(attr) {
			this.AddAttr(attr[i], attr[j])
		}
	}
}

// AddAttrFromInput 附件 "11002,100,15001...."
func (this *Mail) AddAttrFromInput(attr string) error {
	if attr == "" {
		return nil
	}
	arr := strings.Split(attr, ",")
	var i, j int
	var n = len(arr)
	for i = 0; i < n; i += 2 {
		j = i + 1
		if j >= n {
			return values.Errorf(0, "items error") //输入错误
		}
		k, err := strconv.Atoi(arr[i])
		if err != nil {
			return fmt.Errorf("attr error:%v", arr[i])
		}
		v, err := strconv.Atoi(arr[j])
		if err != nil {
			return fmt.Errorf("attr error:%v", arr[j])
		}
		this.AddAttr(int32(k), int32(v))
	}
	return nil
}

func (this *Mail) GetAttrString() string {
	var pair []string
	for _, v := range this.Attr {
		pair = append(pair, fmt.Sprintf("%d,%d", v.K, v.V))
	}
	return strings.Join(pair, ",")
}

// ObjectId xid 竞技场赛季ID,活动ID等 避免不同活动 使用相同模板时重复
// iid 模板ID
func (this *Mail) ObjectId(xid any) {
	this.OID = fmt.Sprintf("%vx%v-%v", this.Uid, this.IID, xid)
}
